package ru.spbau.database.group3.engine;

import ru.spbau.database.group3.parser.ConditionOperator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: Osipov Stanislav
 */
public class HashIndexInfo implements Serializable {


    public HashIndexInfo(String indexName, int indexEntrySize, List<Column> columns) {
        this.indexName = indexName;
        this.indexEntrySize = indexEntrySize;
        this.columns = columns;
    }

    public String getIndexName() {
        return indexName;
    }

    public List<Column> getColumns() {
        return columns;
    }

    public int getIndexEntrySize() {
        return indexEntrySize;
    }

    public boolean isSuitable(List<Condition> conditions) {
        return isEqualityConditions(conditions) && isKeySuitable(conditions);
    }

    public List<Condition> createSearchKey(List<Condition> conditions) {
        List<Condition> searchKey = new ArrayList<Condition>();
        for (Column c : getKeyColumns()) {
            Object value = findColumnValue(conditions, c);
            ConditionOperator cOp = ConditionOperator.E;
            searchKey.add(new Condition(c, value, cOp));
        }
        return searchKey;
    }

    private Object findColumnValue(List<Condition> conditions, Column c) {
        for (Condition condition : conditions) {
            if (condition.getColumn().getName().equals(c.getName())) {
                return condition.getValue();
            }
        }
        throw new IllegalArgumentException("There is no such column " + c.getName());
    }

    private boolean isKeySuitable(List<Condition> conditions) {
        for (Column column : getKeyColumns()) {
            if (!contains(conditions, column)) {
                return false;
            }
        }
        return true;
    }

    private boolean contains(List<Condition> conditions, Column column) {
        for (Condition c : conditions) {
            if (c.getColumn().getName().equals(column.getName())) {
                return true;
            }
        }
        return false;
    }

    private boolean isEqualityConditions(List<Condition> conditions) {
        for (Condition c : conditions) {
            if (c.getOperator() != ConditionOperator.E) {
                return false;
            }
        }
        return true;
    }

    private final String indexName;
    private final int indexEntrySize;
    private List<Column> columns;

    public List<Column> getKeyColumns() {
        return columns.subList(0, columns.size() - 2);
    }
}
